﻿using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NodeEditor
{
    public class RuntimeNode: INode
    {
        StringBuilder stringBuilder = new StringBuilder();
        public AbstractNode node { get; private set; }
        public RuntimePort inputs { get; private set; }
        public RuntimePort outputs { get; private set; }

        public RuntimeNode(AbstractNode node)
        {
            this.node = node;
            inputs = new RuntimePort(node,PortDirection.Input);
            outputs = new RuntimePort(node,PortDirection.Output);
        }

        public string GetKey(string name)
        {
            stringBuilder.Append(node.guid);
            stringBuilder.Append(name);
            var result=  stringBuilder.ToString();
            stringBuilder.Clear();
            return result;
        }

        public T GetInputValue<T>(string field,T defaultValue)
        {
            if (inputs.IsConnect(field))
            {
                var key = this.GetKey(field);
                return inputs.RuntimeValue.GetValue(key, defaultValue);
            }
            return defaultValue;
        }
        public object GetInputValue(string field)
        {
            return inputs.RuntimeValue.GetValue(this.GetKey(field));     
        }

        public void SetOutputValue(string field,object value)
        {
            if (!outputs.IsConnect(field))
                return;

            var edges = outputs[field];

            foreach (var edge in edges)
            {
                var key = edge.input.GetKey(edge.inputKey);
                edge.input.inputs.RuntimeValue.SetValue(key, value);
            }
        }

        public RuntimeNode[] GetConnectNode(string key)
        {
            List<RuntimeNode> result = new List<RuntimeNode>();
            if (inputs.Contains(key))
            {
                result.AddRange(inputs.GetConnectNodes(key));
            }
            else
            {
                result.AddRange(outputs.GetConnectNodes(key));
            }
            return result.ToArray();
        }
        public void Clear()
        {
            inputs.Clear();
            outputs.Clear();
        }
        public RuntimePort ConnectPort(string key, RuntimeEdge edge, NodeEditor.PortDirection direction)
        {
            if (direction == NodeEditor.PortDirection.Input)
            {
                inputs.Connect(key, edge);
                return inputs;
            }
            else
            {
                outputs.Connect(key, edge);
                return outputs;
            }
        }

        public void DisConnectPort(string key, RuntimeEdge edge,NodeEditor.PortDirection direction)
        {
            if (direction == PortDirection.Input)
            {
                inputs.DisConnect(key, edge);
            }
            else
            {
                outputs.DisConnect(key, edge);
            }
        }

        public bool ContainsConnect(RuntimeNode node)
        {
            return inputs.ContainsConnect(node) || outputs.ContainsConnect(node);
        }

        public override string ToString()
        {
            return node.ToString();
        }

        INode[] INode.GetLefts()
        {
            return inputs.GetAllNodes();
        }

        INode[] INode.GetRights()
        {
            return outputs.GetAllNodes();
        }


        
    }
}